﻿#include "opencv.hpp"
using namespace cv;

//生成归一化滤波的卷积核,通过对kernel.ptr(i)[j]的操作来进行
Mat get_blur_kernel(int kernel_size)
{
	Mat kernel = (Mat_<float>(kernel_size, kernel_size));
	for (int i = 0; i < kernel_size; i++)
	{
		for (int j = 0; j < kernel_size; j++)
			kernel.ptr<float>(i)[j] = 1.0 / (kernel_size * kernel_size);
	}
	return kernel;
}



//椒盐噪点产生函数
void salt(cv::Mat& image, int n)
{
	for (int k = 0; k < n; k++)
	{
		int i = rand() % image.cols;
		int j = rand() % image.rows;
		if (image.channels() == 1) {
			image.at<uchar>(j, i) = 255;
		}
		else if (image.channels() == 3) {
			image.at<cv::Vec3b>(j, i)[0] = 255;
			image.at<cv::Vec3b>(j, i)[1] = 255;
			image.at<cv::Vec3b>(j, i)[2] = 255;
		}
	}
}
void pepper(cv::Mat& image, int n)
{
	for (int k = 0; k < n; k++)
	{
		int i = rand() % image.cols;
		int j = rand() % image.rows;
		if (image.channels() == 1) {
			image.at<uchar>(j, i) = 255;
		}
		else if (image.channels() == 3) {
			image.at<cv::Vec3b>(j, i)[0] = 0;
			image.at<cv::Vec3b>(j, i)[1] = 0;
			image.at<cv::Vec3b>(j, i)[2] = 0;
		}
	}
}


int main()
{
	const char* fn = "D:\\opencv class\\lena.jpg";
	Mat	image = imread(fn);
	pyrDown(image, image);
	imshow("原始图像", image);
	
	Mat smooth_image;
	Mat kernel3 = get_blur_kernel(3);
	Mat kernel9 = get_blur_kernel(9);
	Mat kernel27 = get_blur_kernel(29);
	//将核设置好之后，使用函数 filter2D 就可以生成滤波器：
	filter2D(image, smooth_image, -1, kernel3);
	imshow("平均滤波 3*3", smooth_image);

	filter2D(image, smooth_image, -1, kernel9);
	imshow("平均滤波 9*9", smooth_image);
	imshow("原始图像 - 平均滤波 9*9", image - smooth_image);

	filter2D(image, smooth_image, -1, kernel27);
	imshow("平均滤波 27*27", smooth_image);

	Mat gauss_image;
	/*高斯模糊 使图像平滑 过滤噪声 */
	GaussianBlur(image, gauss_image, Size(3, 3), 0);
	imshow("高斯滤波 3*3", gauss_image);

	GaussianBlur(image, gauss_image, Size(9, 9), 0);
	imshow("高斯滤波 9*9", gauss_image);
	imshow("原始图像 - 高斯滤波 9*9", image - gauss_image);

	GaussianBlur(image, gauss_image, Size(27, 27), 0);
	imshow("高斯滤波 27*27", gauss_image);

	Mat mid_image;
	medianBlur(image, mid_image, 3);
	imshow("中值滤波 3", mid_image);

	medianBlur(image, mid_image, 9);
	imshow("中值滤波 9", mid_image);
	imshow("原始图像 - 中值滤波 9", image - mid_image);

	medianBlur(image, mid_image, 27);
	imshow("中值滤波 27", mid_image);

	//加入椒盐噪声
	salt(image, 3000);
	pepper(image, 3000);
	imshow("椒盐噪声图", image);

	//将核设置好之后，使用函数 filter2D 就可以生成滤波器：
	filter2D(image, smooth_image, -1, kernel3);
	imshow("椒盐图平均滤波 3*3", smooth_image);

	GaussianBlur(image, gauss_image, Size(3, 3), 0);
	imshow("椒盐图高斯滤波 3*3", gauss_image);

	medianBlur(image, mid_image, 3);
	imshow("椒盐图中值滤波 3", mid_image);

	waitKey(0);
	destroyAllWindows();
}